<?php

namespace lico\Runtime;

class Loader
{

    protected static $namespaceMap;

    public static function register()
    {
        // 注册系统自动加载
        spl_autoload_register('lico\\Runtime\\Loader::autoload', true, true);
    }

    protected static function autoload($class)
    {

        // p($class);
        if (!empty(self::$namespaceMap[$class])) {
            $original = self::$namespaceMap[$class];
            if (class_exists($original)) {
                if ($original != $class) {
                    class_alias($original, $class, false);
                }
                return $class;
            }
        } else {
            //composer 自动加载
            $composerLoad = self::composerAutoload($class);
            $file = $composerLoad;

            //系统 加载
            $licoNamespace = ROOT_PATH.strtr($class, '\\', DS) . EXT;
            if (!$file && file_exists($licoNamespace)) {
                self::setNamespaceMap($class, $licoNamespace);
                $file = $licoNamespace;
            }
            // p($file);
            if (!$file || !file_exists($file)) {
                // echo $class.'类不存在';
                throw new \Exception($class.'类不存在', 1);
            } else {
                __include_file($file);
                return self::autoload($class);
            }
        }
    }

    /**
     * 设置命名空间加载类字典
     */
    public static function setNamespaceMap($namespace, $class)
    {
        if (empty(self::$namespaceMap[$namespace])) {
            self::$namespaceMap[$namespace] = $class;
        }
    }

    /**
     * composer 自动加载
     */
    public static function composerAutoload($class)
    {
 
        $composerLoad = false;
        if (is_dir(VENDOR_PATH.'composer')) {
            //_需要转换成/
            //例：PHPExcel_IOFactory
            if (is_file(VENDOR_PATH . 'composer'.DS.'autoload_namespaces.php')) {
                $map = require VENDOR_PATH . 'composer'.DS.'autoload_namespaces.php';
                $realClass = strtr($class, '_', '/');
                $namespace = dirname($realClass);
                // p($class,$namespace,$realClass);
                foreach ($map as $ns => $path) {
                    if (strpos($realClass, $ns) === 0) {
                        $realNamespace = current($path).DS.$realClass.EXT;
                        $realNamespace = strtr($realNamespace, '/', DS);
                        $realNamespace = strtr($realNamespace, '\\', DS);
                        // d($realNamespace);
                        if (file_exists($realNamespace)) {
                            self::setNamespaceMap($class, $realNamespace);
                            $composerLoad = $realNamespace;
                        }
                    }
                }
            }
            
            if (is_file(VENDOR_PATH .  'composer'.DS.'autoload_psr4.php')) {
                $map = require VENDOR_PATH .  'composer'.DS.'autoload_psr4.php';//p($map);
                foreach ($map as $ns => $path) {
                    if (strpos($class, $ns) === 0) {
                        $psr4Len = strlen($ns);
                        $extFile = substr($class, $psr4Len);
                        $realNamespace = strtr(current($path).'\\'.$extFile, '\\', DS).EXT;
                        if (file_exists($realNamespace)) {
                            self::setNamespaceMap($class, $realNamespace);
                            $composerLoad = $realNamespace;
                        }
                    }
                }
            }
    
            if (is_file(VENDOR_PATH .  'composer'.DS.'autoload_classmap.php')) {
                $map = require VENDOR_PATH .  'composer'.DS.'autoload_classmap.php';
                foreach ($map as $ns => $path) {
                    if ($ns == $class) {
                        if (file_exists($path)) {
                            self::setNamespaceMap($class, $path);
                            $composerLoad = $path;
                        }
                    }
                }
            }
    
            if (is_file(VENDOR_PATH . 'composer'.DS.'autoload_files.php')) {
                $map = require VENDOR_PATH . 'composer'.DS.'autoload_files.php';
                // foreach ($map as $ns => $path) {
                //      $ns == $class && $file = $path ;
                //      $composerLoad = true;
                // }
            }
        }
        return $composerLoad;
    }
}
